//
//  WBStatusListViewModel.swift
//  TYCWeiBo
//
//  Created by 中发 on 2018/6/5.
//  Copyright © 2018年 中发. All rights reserved.
//

import Foundation
import SDWebImage

///微博列表视图模型
/**
 父类的选择
 --如果要使用‘KVC’或字典转模型框架设置对象值，类就需要继承NSObject
 --如果类只是包装一些代码逻辑，可以不用任何父类，好处是更加轻量级
 --提示：如果用OC写，一律都继承自NSObject即可
 
 使用，负责微博的数据处理
 1.字典转模型
 2.上拉/下拉数据刷新处理
 */
/// 上拉刷新最大尝试次数
private let maxPullUpTryTimes = 3

class WBStatusListViewModel {
    
    //微博视图模型懒加载
    lazy var statusList = [WBStatusViewModel]()
    //上拉刷新错误次数
    private var pullErrorTimes = 0
    
    /// 加载微博列表
    ///
    ///   - pullUp: 是否上拉刷新标记
    /// - Parameter compeletion: 完成回调[网络请求是否成功，是否有更多的上拉刷新]
    
    func loadStatus(pullUp: Bool, compeletion: @escaping (_ isSuccess: Bool, _ hasMorePullUp: Bool) -> ()) {
        //判断是否是上拉刷新，同时检查刷新错误
        if pullUp && pullErrorTimes > maxPullUpTryTimes {
            compeletion(false, false)
        }
        //since_id取出数组第一条微博的id
        let since_id = pullUp ? 0 : (statusList.first?.status.id ?? 0)
        //上拉刷新，取出数组最后一条微博的id
        let max_id = !pullUp ? 0 : (statusList.last?.status.id ?? 0)
        
        // 让数据访问层加载数据
        WBStatusListDAL.loadStatus(since_id: since_id, max_id: max_id) { (list, isSuccess) in
            
//        }
//        //发起网络请求，加载微博数据（字典的数组）
//        WBNetworkManager.shared.statusList(since_id: since_id, max_id: max_id) { (list, isSuccess) in
            
            //0.判断网络是否请求成功
            if !isSuccess{
                //直接回调返回
                compeletion(false, false)
                return
            }
            //字典转模型，（所有第三方都支持嵌套的字典转模型）
            //定义结果可变数组
            var array = [WBStatusViewModel]()
            for dict in list ?? [] {
                //a.创建微博模型--如果创建失败，继续后续的遍历
                guard let model = WBStatus.yy_model(with: dict) else {
                    continue
                }
                //b.将视图model添加到数组
                array.append(WBStatusViewModel(model: model))
            }
            
            print("刷新到\(array.count)数据\(array)")
            //拼接数据
            if pullUp {
                //上拉刷新结束后，将结果拼接在数组的末尾
                self.statusList += array
            } else {
                //下拉刷新,应该将结果数组添加到数组前面
                self.statusList = array + self.statusList
            }
            //判断上拉刷新的数据量
            if pullUp && array.count == 0 {
                self.pullErrorTimes += 1
                compeletion(isSuccess, false)
            }else {
                self.cacheSingleImage(list: array, compeletion: compeletion)
//                //3.完成回调
//                compeletion(isSuccess, true)
            }
        }
    }
    
    
    
    
    
    /// 缓存本次微博下载数组数据中的单张图像
    ///
    /// - 应该缓存完单张图片，并且修改过配图视图的大小后才回调，这样才能保证表格等比例显示单张图像
    /// - Parameter list: 本次下载的视图模型数组
    private func cacheSingleImage(list: [WBStatusViewModel], compeletion: @escaping (_ isSuccess: Bool, _ hasMorePullUp: Bool) -> ()) {
        /// 调度组
        let group = DispatchGroup()
        /// 记录图像长度
        var length = 0
        //遍历数据，查找数组中有单张图像的进行缓存
        for vm in list {
            //判断图像数量
            if vm.picURLs?.count != 1 {
                continue
            }
            //代码执行到此，数组中有且只有一张图片
            guard let pic = vm.picURLs?[0].thumbnail_pic, let url = URL(string: pic) else {
                continue
            }
            print("要缓存的图片是\(pic)")
           /**
             下载图像
                1.downloadImage是SDWebImage的核心方法
                2.图像下载完成后，会自动保存在沙盒中，文件路径是URL的md5
                3.如果沙盒中已经存在图像，那么在后续的使用SD通过URL加载图像，都会通过沙盒加载本地的图像，不会发起网络请求，同时回调方法同样会调用
                4.方法还是同样的方法，调用还是同样的调用，不过内部都不会再发起网络请求
             注意：如果要缓存的图片很大，需要向后台要接口
             */
            //入组
            group.enter()
            SDWebImageManager.shared().imageDownloader?.downloadImage(with: url, options: [], progress: nil, completed: { (image, _, _, _) in
                //将图像转换成二进制数据
                if let image = image, let data = UIImagePNGRepresentation(image){
                    //NSData的长度是length属性
                    length = data.count
                    //图像缓存成功，更新视图
                    vm.updataSingleImageSize(image: image)
                }
                //出组
             group.leave()
            })
        }
        //监听调度组情况
        group.notify(queue: DispatchQueue.main) {
            print("图像缓存完成\(length / 1024) K")
            //执行闭包回调
            compeletion(true, true)
        }
    }
}
